package com.mzj.saas.jobs.commons;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;

/**
 * @Description
 * @Author ???
 * @Date 2018年1月10日下午4:51:39
 * @Version 1.0
 */
public class DateUtils {

    private static final Logger LOG = LoggerFactory.getLogger(DateUtils.class);

    /**
     * yyyyMMddHHmmss
     */
    public static final String FORMAT_14 = "yyyyMMddHHmmss";

    /**
     * yyyyMMddhhmm
     */
    public static final String FORMAT_12 = "yyyyMMddhhmm";
    /**
     * yyyy-MM
     */
    public static final String FORMAT_13 = "yyyy-MM";


    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String FORMAT_DATETIME_14 = "yyyy-MM-dd HH:mm:ss";

    /**
     * yyyy-MM-dd HH:mm:ss.SSS
     */
    public static final String FORMAT_DATETIME_HM_14 = "yyyy-MM-dd HH:mm:ss.SSS";

    public static final String FORMAT_DATATIME_DATE = "yyyy-MM-dd'T'hh:mm:ss.SSSZ";

    /**
     * yyyy-MM-dd HH:mm:ss.SSS
     */
    public static final String FORMAT_HM_14 = "yyyyMMddHHmmssSSS";

    /**
     * yyyyMM
     */
    public static final String FORMAT_6 = "yyyyMM";

    /**
     * MMdd
     */
    public static final String FORMAT_7 = "yyMM";

    /**
     * yyyyMMdd
     */
    public static final String FORMAT_8 = "yyyyMMdd";

    /**
     * yyyy-MM-dd
     */
    public static final String FORMAT_DATE_8 = "yyyy-MM-dd";

    /**
     * yyyy-MM-dd HH:mm
     */
    public static final String FORMAT_DATETIME_15 = "yyyy-MM-dd HH:mm";

    private DateUtils() {

    }

    public static String format(String time, String rformat, String sformat) {
        SimpleDateFormat fmt = new SimpleDateFormat(rformat);
        Date ndate = null;
        try {
            ndate = fmt.parse(time);
            SimpleDateFormat format = new SimpleDateFormat(sformat);
            return format.format(ndate);
        } catch (ParseException e) {
            LOG.error(e.getMessage(), e);
            return null;
        }
    }

    public static String format(Date date, String format) {
        SimpleDateFormat sformat = new SimpleDateFormat(format);
        return sformat.format(date);
    }

    public static Date convert(String time, String format) {
        SimpleDateFormat sformat = new SimpleDateFormat(format);
        try {
            return sformat.parse(time);
        } catch (ParseException e) {
            LOG.error(e.getMessage(), e);
        }
        return null;
    }

    public static String datetimeToString(Date date, String format) {
        Date dateTime = date;
        if (dateTime == null) {
            dateTime = new Date();
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(dateTime);
    }

    public static Date stringToDateTime(String str, String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.parse(str);
    }

    public static String datetimeToStringForTags(Date date, String format) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    public static Date stringToDateTimeForTags(String str, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * when date1 earlier than date2 ,return -1 when date1 equals date2 ,return 0
     * when date1 later than date2 ,return 1
     *
     * @param date1
     * @param date2
     * @return
     * @throws ParseException
     * @throws
     */
    public static int compareDate(String date1, String date2, String dateFormat) throws ParseException {

        DateFormat df = new SimpleDateFormat(dateFormat);

        try {
            Date dt1 = df.parse(date1);
            Date dt2;
            dt2 = df.parse(date2);

            if (dt1.getTime() > dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        } catch (ParseException e) {
            throw e;

        }
    }

    /**
     * 计算2个日期相差多少天
     *
     * @param smdate
     * @param bdate
     * @return
     * @throws ParseException
     */
    public static int daysBetween(Date smdate, Date bdate) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));

        Calendar cal = Calendar.getInstance();

        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();

        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();

        long between_days = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(between_days));

    }

    /**
     * 计算2个日期相差多少小时
     *
     * @param smdate
     * @param bdate
     * @return
     * @throws ParseException
     */
    public static int hoursBetween(Date smdate, Date bdate) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));

        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);

        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);

        long time2 = cal.getTimeInMillis();

        long between_hours = (time2 - time1) / (1000 * 3600);
        return Integer.parseInt(String.valueOf(between_hours));

    }

    /**
     * 得到指定日期，几天前或几天后的日期
     *
     * @param date
     * @param format
     * @param days
     * @return
     */
    public static String getAddDaysTime(String date, String format, int days) {
        Calendar cal = Calendar.getInstance();
        Date fDate = stringToDateTimeForTags(date, format);
        cal.setTime(fDate);
        cal.add(Calendar.DAY_OF_MONTH, days);
        return new SimpleDateFormat(format).format(cal.getTime());
    }

    public static String getAddDaysTime(Date date, String format, int days) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(5, days);
        return (new SimpleDateFormat(format)).format(cal.getTime());
    }

    public static Date getAddDaysTime(Date date, int days) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(5, days);
        return cal.getTime();
    }

    /**
     * 得到指定日期，几分钟前或几分钟后的日期
     *
     * @param date
     * @param format
     * @param minutes
     * @return
     */
    public static String getAddMinutesTime(String date, String format, int minutes) {
        Calendar cal = Calendar.getInstance();
        Date fDate = stringToDateTimeForTags(date, format);
        cal.setTime(fDate);
        cal.add(Calendar.MINUTE, minutes);
        return new SimpleDateFormat(format).format(cal.getTime());
    }

    public static String getAddMinutesTime(Date date, String format, int minutes) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, minutes);
        return (new SimpleDateFormat(format)).format(cal.getTime());
    }

    public static Date getAddMinutesTime(Date date, int minutes) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, minutes);
        return cal.getTime();
    }

    /**
     * 得到指定日期 几天后
     *
     * @param date
     * @param minutes
     * @return
     */
    public static String getAddYEARTime(Date date, String format, int minutes) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_YEAR, minutes);
        return (new SimpleDateFormat(format)).format(cal.getTime());
    }

    /**
     * 获取当前系统下一天日期
     *
     * @param date
     * @return
     */
    public static Date getTomorrow(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, +1);
        date = calendar.getTime();
        return date;
    }

    /**
     * 获取当前系统前一天日期
     *
     * @param date
     * @return
     */
    public static Date getYesterday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        date = calendar.getTime();
        return date;
    }

    /**
     * 根据年 月 获取对应的月份 天数
     */
    public static int getDaysByYearMonth(int year, int month) {

        Calendar a = Calendar.getInstance();
        a.set(Calendar.YEAR, year);
        a.set(Calendar.MONTH, month - 1);
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }

    public static int differentDays(Date date1, Date date2) {
        try {
            Calendar cal1 = Calendar.getInstance();
            cal1.setTime(date1);

            Calendar cal2 = Calendar.getInstance();
            cal2.setTime(date2);
            int day1 = cal1.get(Calendar.DAY_OF_YEAR);
            int day2 = cal2.get(Calendar.DAY_OF_YEAR);

            int year1 = cal1.get(Calendar.YEAR);
            int year2 = cal2.get(Calendar.YEAR);
            if (year1 != year2) { // 同一年
                int timeDistance = 0;
                for (int i = year1; i < year2; i++) {
                    if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {// 闰年
                        timeDistance += 366;
                    } else {// 不是闰年
                        timeDistance += 365;
                    }
                }

                return (timeDistance + (day2 - day1));
            } else {// 不同年
                // System.out.println("判断day2 - day1 : " + (day2 - day1));
                return (day2 - day1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 判断时间段内
     *
     * @param date
     * @param startTime 00:00
     * @param endTime   00:00
     * @return
     */
    @SuppressWarnings("deprecation")
    public static boolean timeHandle(Date date, String startTime, String endTime) {
        int hour = date.getHours();
        int minute = date.getMinutes();

        String minu = String.valueOf(hour > 9 ? hour : String.valueOf(0) + String.valueOf(hour))
                + String.valueOf(minute > 9 ? minute : String.valueOf(0) + String.valueOf(minute));
        startTime = startTime.replaceAll(":", "");
        endTime = endTime.replaceAll(":", "");
        if (Long.parseLong(minu) >= Long.parseLong(startTime) && Long.parseLong(minu) <= Long.parseLong(endTime)) {
            return true;
        }

        return false;
    }

    /**
     * 判断时间段相差
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int getMinutesDiff(String startDate, String endDate) {
        int ret = 0;

        String startDateStr[] = startDate.split(":");
        String endDateStr[] = endDate.split(":");
        if (startDateStr[0].startsWith("0")) {
            startDateStr[0] = startDateStr[0].substring(1);
        }
        if (startDateStr[1].startsWith("0")) {
            startDateStr[1] = startDateStr[1].substring(1);
        }
        if (endDateStr[0].startsWith("0")) {
            endDateStr[0] = endDateStr[0].substring(1);
        }
        if (endDateStr[1].startsWith("0")) {
            endDateStr[1] = endDateStr[1].substring(1);
        }
        int s = Integer.parseInt(startDateStr[0]) * 60 + Integer.parseInt(startDateStr[1]);
        int e = Integer.parseInt(endDateStr[0]) * 60 + Integer.parseInt(endDateStr[1]);
        ret = e - s;
        return ret;
    }

    /**
     * 判断当天时是每月的第一天
     *
     * @return true是 false否
     */
    public static boolean dayOne() {
        Calendar c = Calendar.getInstance();
        int date = c.get(Calendar.DATE);
        if (date == 1)
            return true;
        else
            return false;
    }

    /**
     * 当前时间到凌晨0:00之间秒
     *
     * @return
     */
    public static Long getTimeMillis() {
        long current = System.currentTimeMillis();// 当前时间毫秒数
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long tomorrowzero = calendar.getTimeInMillis();
        long tomorrowzeroSeconds = (tomorrowzero - current) / 1000;
        return tomorrowzeroSeconds;
    }

    /**
     * 获取时间前几天的时间
     *
     * @param referenceDate
     * @param day
     * @return
     */
    public static Date getPreDay(Date referenceDate, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(referenceDate);
        calendar.add(Calendar.DATE, -day);
        return calendar.getTime();
    }

    /**
     * 获取时间秒数
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getTimeInMillis(Date date) throws ParseException {

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        long time = cal.getTimeInMillis();

        return String.valueOf(time);
    }


    /**
     * 获取最小日期
     *
     * @param date
     * @return
     */
    public static Date getMintDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());

        // 通过LocalDateTime的 with方法设置某天的最小值和最大值！！
        LocalDateTime minDateTime = localDateTime.with(LocalTime.MIN);
        // 格式化日期
        Date fromDate = Date.from(minDateTime.atZone(ZoneId.systemDefault()).toInstant());

        return fromDate;
    }

    /**
     * 获取最大日期
     *
     * @param date
     * @return
     */
    public static Date getMaxDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime maxDateTime = localDateTime.with(LocalTime.MAX);
        return Date.from(maxDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取指定月份的最大时间
     *
     * @return
     */

    public static String getLastDayOfMonth1(Date date) throws ParseException {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //设置年份
        //cal.set(Calendar.YEAR, date.getYear());
        //设置月份
        //cal.set(Calendar.MONTH, date.getMonth() - 1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DATE);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.FORMAT_DATETIME_14);
        Date maxDay = getMaxDay(sdf.parse(sdf.format(cal.getTime())));
        return DateUtils.format(maxDay, DateUtils.FORMAT_DATETIME_14);
    }

    /**
     * 获取指定月份的最小时间
     *
     * @param
     * @param
     * @return
     */
    public static String getFirstDayOfMonth1(Date date) throws ParseException {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //设置年份
        //cal.set(Calendar.YEAR, cal.get(Calendar.YEAR));
        //设置月份
        //cal.set(Calendar.MONTH,cal.get(Calendar.MONTH) - 1);
        //获取某月最小天数
        int firstDay = cal.getMinimum(Calendar.DATE);
        //设置日历中月份的最小天数
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.FORMAT_DATETIME_14);

        Date mintDay = getMintDay(sdf.parse(sdf.format(cal.getTime())));

        return DateUtils.format(mintDay, DateUtils.FORMAT_DATETIME_14);
    }
}
